package com.system.core.utils;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class DigitAssets implements Serializable, Comparable<DigitAssets> {
    // 最小单位整数倍。例如：0.00000001时为1。
    private long tinyNum;

    // 最大值
    public static final long MAX_VALUE = 99999999999999999L;

    // 小数位数
    public static final int DEFAULT_DIGITS = 8;
    // 精度后面所有直接去除
    public static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.DOWN;

    // 小数点后8位，不足补0
//    public static final DecimalFormat fmtEight = new DecimalFormat("##,###,###,###,##0.00000000");
    public static final DecimalFormat fmtEight = new DecimalFormat("#############0.00000000");
    // 小数点后4位，不足补0
    public static final DecimalFormat fmtFour = new DecimalFormat("##,###,###,###,##0.0000");
    // 小数点后2位，不足补0
    public static final DecimalFormat fmtTwo = new DecimalFormat("##,###,###,###,##0.00");

    static {
        fmtEight.setRoundingMode(RoundingMode.DOWN);
        fmtFour.setRoundingMode(RoundingMode.DOWN);
        fmtTwo.setRoundingMode(RoundingMode.DOWN);
    }


    /**
     * 静态方法，初始0资产
     */
    public static DigitAssets zero() {
        return new DigitAssets();
    }


    /**
     * 静态方法，初始资产
     */
    public static DigitAssets num(String num) {
        if (num == null) {
            return DigitAssets.zero();
        }
        num = num.trim();
        if (num.contains(",")) {
            num = num.replace(",", "");
        }
        DigitAssets money = new DigitAssets(num);
        return money;
    }
    public static DigitAssets num(double num) {
        DigitAssets money = new DigitAssets(Double.toString(num));
        return money;
    }
    public static DigitAssets num(long num) {
        DigitAssets money = new DigitAssets(Long.toString(num));
        return money;
    }
    public static DigitAssets num(BigDecimal num) {
        DigitAssets money = new DigitAssets(num);
        return money;
    }


    /**
     * 构造方法
     * 因BigDecimal浮点损失精度，屏蔽double/long构造函数
     */
    public DigitAssets() {
        this.tinyNum = 0L;
    }

    public DigitAssets(String num) {
    	this(new BigDecimal(num == null ? "" : num.replace(",", "")));
    }

    public DigitAssets(BigDecimal num) {
        if (num == null) {
            this.tinyNum = 0L;
        } else {
            this.tinyNum = this.rounding(num.movePointRight(DEFAULT_DIGITS), DEFAULT_ROUNDING_MODE);
        }
    }


    protected DigitAssets newDigitAssets(long tinyNum) {
        DigitAssets money = new DigitAssets();
        money.setTinyNum(tinyNum);
        return money;
    }

    public void setNum(BigDecimal num) {
        this.tinyNum = this.rounding(num.movePointRight(DEFAULT_DIGITS), DEFAULT_ROUNDING_MODE);
    }

    public BigDecimal getNum() {
        return BigDecimal.valueOf(this.tinyNum, DEFAULT_DIGITS);
    }

    public void setTinyNum(long tinyNum) {
        this.tinyNum = tinyNum;
    }

    public long getTinyNum() {
        return this.tinyNum;
    }


    /**
     * 加减乘除运算
     */
    public DigitAssets add(DigitAssets other) {
        return newDigitAssets(this.tinyNum + other.tinyNum);
    }

    public DigitAssets addTo(DigitAssets other) {
        this.tinyNum += other.tinyNum;
        return this;
    }

    public DigitAssets divide(double val) {
        return this.divide(new BigDecimal(val));
    }

    public DigitAssets divide(BigDecimal val) {
        return new DigitAssets(this.getNum().divide(val, DEFAULT_DIGITS, DEFAULT_ROUNDING_MODE));
    }


    public DigitAssets subtract(DigitAssets other) {
        return newDigitAssets(this.tinyNum - other.tinyNum);
    }

    public DigitAssets subtractFrom(DigitAssets other) {
        this.tinyNum -= other.tinyNum;
        return this;
    }

    public DigitAssets multiply(BigDecimal val) {
        BigDecimal newVal = BigDecimal.valueOf(this.tinyNum).multiply(val);
        return newDigitAssets(this.rounding(newVal, DEFAULT_ROUNDING_MODE));
    }

    public DigitAssets multiply(double val) {
        return newDigitAssets(Math.round(this.tinyNum * val));
    }

    public DigitAssets multiply(long val) {
        return newDigitAssets(this.tinyNum * val);
    }


    @Override
    public int compareTo(DigitAssets other) {
        if (this.tinyNum < other.tinyNum) {
            return -1;
        } else {
            return this.tinyNum == other.tinyNum ? 0 : 1;
        }
    }

    /**
     * 是否大于0
     */
    public Boolean greaterThanZero() {
        return this.tinyNum > 0 ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 是否等于0
     */
    public Boolean equalZero() {
        return this.tinyNum == 0 ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 是否小于0
     */
    public Boolean lessThanZero() {
        return this.tinyNum < 0 ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 是否 小于等于 最大值
     */
    public Boolean lessAndEqualMax() {
        return this.tinyNum <= MAX_VALUE ? Boolean.TRUE : Boolean.FALSE;
    }

    /**
     * 取值范围是否有效
     */
    public Boolean rangeLegal() {
        return (greaterThanZero() && lessAndEqualMax()) ? Boolean.TRUE : Boolean.FALSE;
    }

    private long rounding(BigDecimal val, RoundingMode roundingMode) {
        return val.setScale(0, roundingMode).longValue();
    }

    public String getStandardString() {
        return toStandardString();
    }

    public String getDecimalFourString() {
        return toStandardString(fmtFour);
    }

    public String getDecimalTwoString() {
        return toStandardString(fmtTwo);
    }

    @Override
    public String toString() {
        return this.getNum().toString();
    }

    public String toStandardString() {
    	return toStandardString(fmtEight);
    }

    public String toStandardString(DecimalFormat fmt) {
        return fmt.format(this.getNum());
    }

    public Money toMoney() {
        return new Money(this.getDecimalTwoString());
    }

    public static void main(String[] args) {
//        DigitAssets demo = DigitAssets.num("0.000000016");
//        System.out.println(demo.getNum());
//        System.out.println(demo.getNum().doubleValue());
//        System.out.println(demo.toStandardString());
//        System.out.println(demo.getNum().doubleValue() > 0);

//        System.out.println(DigitAssets.num(0.3));
//        System.out.println(new DigitAssets(0.3));

//        DigitAssets demo = DigitAssets.num(0L);
//        System.out.println(demo.rangeLegal());

//        DigitAssets demo = DigitAssets.num("123456789");
//        DigitAssets demo = DigitAssets.num("123456789.123456789");
//        DigitAssets demo = DigitAssets.num("123456789.1666666666");
////        DigitAssets demo = DigitAssets.num("0");
//        System.out.println(demo.getStandardString());
//        System.out.println(demo.getDecimalFourString());
//        System.out.println(demo.getDecimalTwoString());
//        System.out.println(DigitAssets.num(demo.getStandardString()));
        
        String num = "2,974,636.70849700";
		if (num.contains(",")) {
            num = num.replace(",", "");
        }
		System.out.println(num);

//        DigitAssets demo = DigitAssets.num(1);
//        System.out.println(demo.divide(3));
    }
}
